import hatch_interface
import logging
from os.path import splitext
import time


logger = logging.getLogger(splitext(__file__)[0])
del splitext
logger.setLevel(logging.DEBUG)
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)  # Log debug to console.
#formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
#consoleHandler.setFormatter(formatter)
logger.addHandler(consoleHandler)
fileHandler = logging.FileHandler(__file__+'.log', 'a')
fileHandler.setLevel(logging.INFO)  # Log info to file for storing results.
logger.addHandler(fileHandler)
print "Logging to " + fileHandler.baseFilename


options = {}    # Only need to set non-default options.  See optionDefaults for valid keys.
options["xmlFile"] = 'byron_hatch.xml'
options["bus"] = 'byron'
options["historyFile"] = __file__
options["debug"] = False

hi = hatch_interface.setup_interface(options)

def getInt(prompt="Enter an integer: "):
    got = ""
    while not got.isdigit():
        got = raw_input(prompt)         
    return int(got)

def getYesNo(prompt="Enter y/N: "):
    yesNo = ""
    while not (yesNo == 'y' or yesNo == 'Y' or yesNo == 'n' or yesNo == 'N'):
        yesNo = raw_input(prompt)
    return yesNo.lower()


tagNo = getInt("Please enter tag number (in decimal): ")
logger.info("\n\nTag number: " + repr(tagNo))
hi.put(0x31, 0x41, 0x59, 0x26)  # Reset DUT.
time.sleep(1)


# Read JTAG revision for sanity check.
if True:
    logger.info("JTAG revision is: " + repr(hi.byron.jtag_revision.read()))

# Read PROM & check not empty.
if True:
    promValues = hi.byron.prom.readDepthFirst()
    empty = True
    while empty:
        if (0xff ^ promValues.pop(0)) > 0:
            empty = False
    if empty:
        logger.info("PROM is empty!!")
    else:
        logger.info("PROM not empty.")

# Read byte.
if True:
    logger.info("PROM extra config reserved byte is: " + repr(hi.byron.prom.extra_config0.reserved_byte0.read()))

# Write byte & read to check.
if False:
    logger.info("Writing PROM extra config byte to: " + repr(tagNo))
    hi.byron.prom.extra_config0.reserved_byte0.write(tagNo)
    readTagNo = hi.byron.prom.extra_config0.reserved_byte0.read()
    if readTagNo != tagNo:
        logger.info("Wrote PROM extra config byte to: " + repr(readTagNo) + "Failed prom write!")
    else:
        logger.info("Wrote PROM extra config byte to: " + repr(readTagNo))


# Configure & test PLL.
if True:
    hi.byron.d_core.control.enable_update_from_otp.write(0)
    hi.byron.d_core.polynomial_lsb.write(0x00)
    hi.byron.d_core.polynomial_msb.write(0x00)
    hi.byron.acontrol.enable_pll_fast.write(0)
    hi.byron.d_core.pll_config.config(0x2)  # Use strongest locking current.
    hi.byron.acontrol.enable_pll.write(1)
    hi.byron.d_core.control.run_poly.write(1)
    hi.byron.d_core.tx_sample01.writeBreadthFirst(0xf, 0xf)
    hi.byron.d_core.tx_sample23.writeBreadthFirst(0xf, 0xf)

    tuneIndex = 0
    tuneMod = 32
    tunedValue = None
    tuned = False   # Tune the Frequency: Find the setting that is closest to 916MHz.
    while not tuned:
        found = False
        while not found:
            hi.byron.d_core.tune.pll.write(tuneIndex)
            print "Tuned value (decimal): " + repr(tuneIndex)
            print "Hit enter to tune to the next value, or any character if ~ 916 MHz already found."
            found = len(raw_input()) > 0
            tuneIndex += 1
            tuneIndex %= tuneMod

        value = raw_input("Please enter the value to use for ~ 916 MHz ('f/F' to fail, else to repeat tuning): ")
        if value.isdigit():
            tunedValue = int(value)
            hi.byron.d_core.tune.pll.write(tunedValue)
            logger.info("Tuned to ~ 916 MHz at: " + repr(tunedValue))
            tuned = True
        elif value == 'f' or value == 'F':
            logger.info("Tuned to ~ 916 MHz at: Could not tune!")

    # See if PLL locking drops out (and repeat at lesser currents.)
    if tunedValue is not None:
        hi.byron.acontrol.enable_pll_fast.write(1)  # PLL should lock - peak should move a little.
        hi.byron.acontrol.enable_pll_fast.write(0)  # Should stay locked.  if not this chip fails.

        yesNo = getYesNo(prompt="Did PLL lock & stay locked? Enter y/N: ")
        if yesNo == 'y':   # Turn down power & see if it stays locked.
            hi.byron.d_core.pll_config.config.write(0x0)  # Use mid-range locking current.
            yesNo = getYesNo(prompt="power turned down. Did PLL lock & stay locked? Enter y/N: ")
        if yesNo == 'y':   # Turn down power & see if it stays locked.
            hi.byron.d_core.pll_config.config.write(0x4)  # Use weakest locking current.
            yesNo = getYesNo(prompt="power turned down. Did PLL lock & stay locked? Enter y/N: ")
        if yesNo == 'n':
            logger.info("Lost lock at power of: " + repr(hi.byron.d_core.pll_config.config.read()))
        else:
            logger.info("Did not lose lock at any power.")


    # BPSK test.
    if True:
        hi.put(0x31, 0x41, 0x59, 0x26)  # Reset DUT.
        hi.byron.d_core.control.enable_update_from_otp.write(0)
        hi.byron.d_core.polynomial_lsb.write(0x53)
        hi.byron.d_core.polynomial_msb.write(0x00)
        hi.byron.acontrol.enable_pll_fast.write(0)
        hi.byron.d_core.pll_config.config(0x2)  # Use strongest locking current.
        hi.byron.acontrol.enable_pll.write(1)
        hi.byron.d_core.control.run_poly.write(1)
        hi.byron.d_core.tx_sample01.writeBreadthFirst(0xf, 0xf)
        hi.byron.d_core.tx_sample23.writeBreadthFirst(0xf, 0xf)

        hi.byron.d_core.tune.pll.write(tunedValue)
        hi.byron.acontrol.enable_pll_fast.write(1)  # PLL should lock - peak should move a little.
        hi.byron.acontrol.enable_pll_fast.write(0)  # Should stay locked.  if not this chip fails.

        yesNo = getYesNo("Do you see a BPSK signal? Enter y/N: ")
        if yesNo == 'y':
            logger.info("BPSK signal visible: " + repr(yesNo))
        else:
            logger.info("BPSK signal visible: " + repr(False) + "!")


hi.put(0x31, 0x41, 0x59, 0x26)  # Reset DUT.
print "Testing is Done!"


